/*******************************************************************************
 * Copyright (c) 2012 Clever Devices.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Public License v3.0
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/gpl.html
 * 
 * Contributors:
 * 	Clever Devices Interns - 
 * 	Alex Frankel, Andria Young, Kevin Thomas, Nicholas Culpepper, Taner Oztimurlenk, Thomas Volberg
 ******************************************************************************/
package com.framework.bustime;

import java.util.ArrayList;
import java.util.Calendar;

import android.app.AlarmManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.ProgressDialog;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

import com.framework.beans.Prediction;
import com.framework.beans.Route;
import com.framework.beans.Stop;
import com.framework.bustime_parser.ApiHandler;
import com.framework.cleverstop_tentative.BusTimeMainActivity;
import com.framework.cleverstop_tentative.MainMenu;
import com.framework.cleverstop_tentative.R;
import com.framework.menu.ArrivalsGridAdapter;
import com.framework.menu.MenuAdapter;
import com.framework.menu.MenuItem;
import com.slidingmenu.lib.SlidingMenu;
import com.slidingmenu.lib.app.SlidingActivity;


/**
 * Analagous to the Arrivals Grid from any given BusTime website.
 * Allows for the input of route, direction and stop to deliver the next predictions
 * for said stop from the BusTime API.  This activity can also by called by the BusTimeMainActivity,
 * in which case the system is designed to load arrival times for the destination of the bus selected
 * on the BusTime map
 * 
 * @author AFrankel
 *
 */
public class ArrivalsGrid extends SlidingActivity implements
		OnItemClickListener, OnItemSelectedListener, OnClickListener {

	public ArrivalsGrid() {
		super();
	}

	public synchronized void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		ah = new ApiHandler();

		loading = true;

		canClickDirection = false;
		canClickStop = false;

		/*
		 * For use with the demo.
		 * If the arrival grid is called after a confirmed
		 * NFC Payment.  The NFCActivity passes all information about the
		 * Bus to get an accurate arrivals grid for the final destination.
		 */
		Bundle b = getIntent().getExtras();
		if (b != null) {
			stopId = b.getString("stopId");
			fromNfc = b.getBoolean("fromNfc");
		}

		// only do the following if this activity was called by the NFC activity
		if (fromNfc) {
//			NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
//
//			Intent i = new Intent(this, BusTimeMainActivity.class);
//			PendingIntent pi = PendingIntent.getActivity(this, 0, i, 0);
//			String body = "You will be arriving in 1 minute";
//			String title = "Prediction Alarm";
//
//			Notification n = new Notification(R.drawable.alert, body,
//					System.currentTimeMillis());
//			n.setLatestEventInfo(this, title, body, pi);
//			
//			
//			n.defaults = Notification.DEFAULT_ALL;
//			nm.notify(uniqueID, n);
//			nm.cancel(uniqueID);

			Calendar cal = Calendar.getInstance();
			cal.add(Calendar.SECOND,15);
			Intent intent = new Intent(ArrivalsGrid.this, BusTimeBroadcastReceiver.class);
			//intent.putExtra(name, value)
			PendingIntent sender = PendingIntent.getBroadcast(this, 192837, intent, PendingIntent.FLAG_UPDATE_CURRENT);
			
			AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
			am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), sender);
			
			
			
		}

		// sets main view
		setContentView(R.layout.arrivals_grid);
		setSlidingMenu();
		routesList = (ListView) findViewById(R.id.arrivalsList);

		routeSpinner = (Spinner) findViewById(R.id.arrivalsRoute);
		getRoutes();
		routes.add(0, new Route("(Select Route)", ""));
		ArrayAdapter<Route> routesAdapter = new ArrayAdapter<Route>(this,
				android.R.layout.simple_spinner_dropdown_item, routes);
		routeSpinner.setAdapter(routesAdapter);
		routeSpinner.setOnItemSelectedListener(this);

		directionSpinner = (Spinner) findViewById(R.id.arrivalsDirection);
		stopSpinner = (Spinner) findViewById(R.id.arrivalsStop);

		routeButton = (Button) findViewById(R.id.routeButton);
		directionButton = (Button) findViewById(R.id.directionButton);
		stopButton = (Button) findViewById(R.id.stopButton);

		routeButton.setOnClickListener(this);
		directionButton.setOnClickListener(this);
		stopButton.setOnClickListener(this);

		Drawable d = this.getResources().getDrawable(
				R.drawable.layout_background);
		getActionBar().setBackgroundDrawable(d);
		getActionBar().setHomeButtonEnabled(true);

		// this is an id for a STOP
		final String testId = "8345";

		//Only loads prediction if passed bus/stop information
		if (b != null) {
			Thread background = new Thread() {
				public void run() {

					predictions = displayPredictionsForStop(stopId);
					loading = false;
				}
			};
			background.start();

			while (loading) {
				try {
					wait(500);
					System.out.println("Loading Predictions");
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}

			if (fromNfc) {
				predictions.add(0, new Prediction("Test", "1234", "4", "TEST",
						"00000 10:00", "0000 10:07"));
				ArrivalsGridAdapter adapter = new ArrivalsGridAdapter(this,
						R.layout.arrivals_grid_row, predictions);
				routesList.setAdapter(adapter);
			}
		}
	}

	public ArrayList<Prediction> displayPredictionsForStop(String stopId) {
		String xml = ah.getXML(ApiHandler.GET_PREDICTIONS + "stpid=" + stopId);
		predictions = ah.getPredicitons(xml);

		return predictions;
	}

	public void displayPredictionsForRoute(String routeId, String stopId) {
		ah.getXML(ApiHandler.GET_ROUTES + "rt=" + routeId + "stpid=" + stopId);

	}

	public void setIDs() {

	}

	/**
	 * Sets up properties for the sliding menu this will keep properties
	 * consistent across all activities
	 */
	public void setSlidingMenu() {
		// sets view that slides out from left, this will be standard across all
		// menus
		// allowing for quick and intuitive navigation
		setBehindContentView(R.layout.persistent_menu_list);

		MenuItem[] menuItems = {
				new MenuItem("Rewards", R.drawable.rewaredsicon, "1"),
				new MenuItem("Cust. Service", R.drawable.boardsicon, ""),
				new MenuItem("Fares", R.drawable.faresicon, ""),
				new MenuItem("BusTime", R.drawable.bustimeicon, ""),
				new MenuItem("Settings", R.drawable.settinsicon, "") };

		ArrayList<MenuItem> items = new ArrayList<MenuItem>();
		for (int i = 0; i < menuItems.length; i++)
			items.add(menuItems[i]);

		/*
		 * String[] listItems = { "Rewards", "Boards", "Fares", "BusTime" };
		 * ArrayList<String> list = new ArrayList<String>();
		 * list.addAll(Arrays.asList(listItems)); /* listData = new
		 * ArrayAdapter<String>(this, R.layout.slider_pullout_row, list);
		 */
		listData = new MenuAdapter(this, R.layout.listview_item_row, items);

		mainList = (ListView) findViewById(R.id.menuList);

		// dynamically add items to listView
		// did below as a test, but can easily add items based on the section of
		// app you are in
		// listData.insert("BusTime", list.size());

		mainList.setAdapter(listData);
		mainList.setOnItemClickListener(this);

		getSlidingMenu().setBehindOffsetRes(R.dimen.DistanceFromSide);
		getSlidingMenu().setBehindScrollScale(0.5f);
		getSlidingMenu().setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);
		// getSlidingMenu().setAboveTouchMode(SlidingMenu.TOUCHMODE_MARGIN);
		// getSlidingMenu().setBehindTouchMode(SlidingMenu.TOUCHMODE_FULLSCREEN);
		getSlidingMenu().setActivated(true);

	}

	@Override
	public void onItemClick(AdapterView<?> parent, View view, int index, long id) {
		// TODO Auto-generated method stub
		switch (index) {

		// this is where each intent will be started for all of your
		// respective sections. Look to the "BUSTIME" case as a model
		case REWARDS:
			Intent Rewards = new Intent("com.framework.rewards.REWARDS");
			startActivity(Rewards);
			break;
		case BOARDS:
			Intent Boards = new Intent("com.framework.customerservice.CUSTOMER");
			startActivity(Boards);
			break;
		case FARES:
			Intent Fares = new Intent(
					"com.framework.cleverstop_tentative.FARESMAINACTIVITY");
			startActivity(Fares);
			break;
		case BUSTIME:
			Intent BusTime = new Intent(
					"com.framework.cleverstop_tentative.BUSTIMEMAINACTIVITY");
			startActivity(BusTime);
			break;
		}
	}

	public synchronized void getRoutes() {
		Thread background = new Thread() {
			public synchronized void run() {
				try {
					String xml = ah.getXML(ApiHandler.GET_ROUTES);
					routes = ah.getRoutes(xml);
					loading = false;
					// notifyAll();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		};
		background.start();

		while (loading) {
			try {
				wait(500);
				System.out.println("Loading Routes");
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		// REALLY shitty programming
		// I know little to nothing about thread management but apparently the right
		// practice here is to use a Handler
		// this is just so that the while(loading) statement works as designed
		// if you have questions -- AF wrote this
		loading = true;

	}

	/**
	 * called after an item has been selected in the route spinner (see onItemSelected)
	 * 
	 * @param route requirement for getDirections API call
	 */
	public synchronized void getDirectionsForRoute(final String route) {
		loading = true;
		Thread background = new Thread() {
			public synchronized void run() {
				try {
					String xml = ah.getXML(ApiHandler.GET_DIRECTIONS + route);
					directions = ah.getDirectionsForRoute(xml);
					loading = false;
					// notifyAll();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		};
		background.start();

		while (loading) {
			try {
				wait(500);
				System.out.println("Loading Directions");
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		// REALLY shitty programming
		// this is just so that the while(loading) statement works as designed
		// if you have questions -- AF wrote this
		loading = true;
	}

	/**
	 * called after both the route and direction spinner items have a selection.
	 * @param route requirement for getStops API call
	 * @param direction requirement for getStops API call
	 */
	public synchronized void getStopsForRouteAndDirection(final String route,
			final String direction) {
		loading = true;
		Thread background = new Thread() {
			public synchronized void run() {
				try {
					String xml = ah.getXML(ApiHandler.GET_STOPS + route
							+ ApiHandler.addDirection(direction));
					stops = ah.getStops(xml);
					loading = false;
					// notifyAll();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		};
		background.start();

		while (loading) {
			try {
				wait(500);
				System.out.println("Loading Stops");
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		// REALLY shitty programming
		// this is just so that the while(loading) statement works as designed
		// if you have questions -- AF wrote this
		loading = true;

	}

	@Override
	public synchronized void onItemSelected(AdapterView<?> parent, View view,
			int index, long id) {
		switch (parent.getId()) {
		case R.id.arrivalsRoute:
			if (index == 0)
				return;
			getDirectionsForRoute(((Route) routeSpinner.getSelectedItem())
					.getId());
			directions.add(0, "(Select Direction)");
			ArrayAdapter<String> directionsAdapter = new ArrayAdapter<String>(
					this, android.R.layout.simple_spinner_dropdown_item,
					directions);
			directionSpinner.setAdapter(directionsAdapter);
			directionSpinner.setOnItemSelectedListener(this);
			
			//insures Spinner is not selectable until route has been selected
			canClickDirection = true;
			break;

		case R.id.arrivalsDirection:
			if (index == 0)
				return;
			getStopsForRouteAndDirection(
					((Route) routeSpinner.getSelectedItem()).getId(),
					directionSpinner.getSelectedItem().toString());
			ArrayAdapter<Stop> stopsAdapter = new ArrayAdapter<Stop>(this,
					android.R.layout.simple_spinner_dropdown_item, stops);
			stopSpinner.setAdapter(stopsAdapter);
			stopSpinner.setOnItemSelectedListener(this);
			canClickStop = true;
			break;

		case R.id.arrivalsStop:
			if (index == 0)
				return;

			System.out.println("STOP ID: "
					+ ((Stop) stopSpinner.getSelectedItem()).getStopId());
			Thread background = new Thread() {
				public void run() {

					predictions = displayPredictionsForStop(((Stop) stopSpinner
							.getSelectedItem()).getStopId());
					loading = false;
				}
			};
			background.start();

			while (loading) {
				try {
					wait(500);
					System.out.println("Loading Predictions");
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}

			ArrivalsGridAdapter adapterUpdate = new ArrivalsGridAdapter(this,
					R.layout.arrivals_grid_row, predictions);
			routesList.setAdapter(adapterUpdate);

			loading = true;
			break;
		}

	}

	@Override
	public void onNothingSelected(AdapterView<?> arg0) {
		// TODO Auto-generated method stub

	}

	
	/**
	 * These buttons perform the actions of the Spinners.  This was a formatting issue
	 * You will see in the XML for the ArrivlasGrid that the Spinners all have a width and
	 * height of 0dp.
	 */
	
	@Override
	public void onClick(View view) {
		switch (view.getId()) {
		case R.id.routeButton:
			routeSpinner.performClick();
			break;

		case R.id.directionButton:
			if (canClickDirection) {
				directionSpinner.performClick();
				break;
			} else {
				//called if no selection of the route spinner has been made
				Toast.makeText(getApplicationContext(),
						"Please Select Route First", Toast.LENGTH_SHORT).show();
				break;
			}

		case R.id.stopButton:
			if (canClickStop) {
				stopSpinner.performClick();
				break;
			} else {
				//called if no selection of the direction spinner has been made
				Toast.makeText(getApplicationContext(),
						"Please Select Direction First", Toast.LENGTH_SHORT)
						.show();
				break;
			}
		}
	}

	@Override
	public boolean onOptionsItemSelected(android.view.MenuItem item) {
		//open sliding menu
		toggle();
		return true;
	}
	
	/**
	 * None of this ended up working.  Idea was to set up a timed alert to go
	 * off at a certain point during the demo
	 * 
	 * @param view
	 */
	public void startAlert(View view){
		int additionalTimeInMills = 10000;
		Intent intent = new Intent(this, BusTimeBroadcastReceiver.class);
		PendingIntent pi = PendingIntent.getBroadcast(this.getApplicationContext(),
				123456789, intent, 0);
		AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
		am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()+additionalTimeInMills,
				pi);
	}

	ApiHandler ah;
	ArrayList<Prediction> predictions;
	ArrayList<Route> routes;
	ArrayList<String> directions;
	ArrayList<Stop> stops;

	ListView routesList;
	boolean loading;
	ListView mainList;
	MenuAdapter listData;
	ListAdapter realListData;
	public final int REWARDS = 0;
	public final int BOARDS = 1;
	public final int FARES = 2;
	public final int BUSTIME = 3;

	Spinner routeSpinner;
	Spinner directionSpinner;
	Spinner stopSpinner;

	boolean canClickDirection;
	boolean canClickStop;

	Button routeButton, directionButton, stopButton;
	String stopId;
	boolean fromNfc = false;

	static final int uniqueID = 1234567;

}
